#include "scriptenvironment.h"

#include <QCompleter>
#include <QtScript>

#include "application.h"
#include "zonesmanager.h"
#include "alertwindow.h"
#include "optrzone.h"
#include "expandingwindow.h"
#include <windows.h>
#include "nativewindow.h"

O_Z

#define optra() OZ
        extern ZonesManager * zmanager;

QScriptValue script_output(QScriptContext *, QScriptEngine *);
QScriptValue script_help(QScriptContext *, QScriptEngine *);
QScriptValue script_window(QScriptContext *, QScriptEngine *);


ScriptEnvironment::ScriptEnvironment(ScriptEnvironmentMode mode, QObject *parent) :
        QObject(parent)
{
    engine = new QScriptEngine;
    QScriptValue fun = engine->newFunction(script_output);
    fun.setData(engine->newQObject(this));
    engine->globalObject().setProperty("print", fun);

    fun = engine->newFunction(script_help);
    fun.setData(engine->newQObject(this));
    engine->globalObject().setProperty("help", fun);

    fun = engine->newFunction(script_window);
    fun.setData(engine->newQObject(this));
    engine->globalObject().setProperty("window", fun);

    if (mode == full){
        QScriptValue globalObject = engine->globalObject();

        if (!globalObject.property("optra").isObject()){
            QScriptValue mainZoneObject = engine->newQObject(optra());
            engine->globalObject().setProperty("optra", mainZoneObject);
        }


        ZonesManager::ZoneProcessMap m = zmanager->zoneProcess();
        foreach(ZoneProcess p, m){
            if (!globalObject.property(p.info->id()).isObject()){
                QScriptValue zo = engine->newQObject(p.zinterface);
                engine->globalObject().setProperty(p.info->id(), zo);
            }

        }
    }
}

ScriptEnvironment::~ScriptEnvironment()
{
    delete engine;
}

bool ScriptEnvironment::exec(const QString& script)
{
    QScriptValue res = engine->evaluate(script);
    if (res.isError()){
        emit output(res.toString());
        return false;
    }
    return true;
}

void ScriptEnvironment::print(const QString& out)
{
    emit output(out);
}

QScriptValue script_output(QScriptContext *context, QScriptEngine *engine)
{
    QString result;
    for (int i = 0; i < context->argumentCount(); ++i) {
        if (i > 0)
            result.append(" ");
        result.append(context->argument(i).toString());
    }

    QScriptValue calleeData = context->callee().data();
    ScriptEnvironment *par = qobject_cast<ScriptEnvironment*>(calleeData.toQObject());
    par->print(result);
    return engine->undefinedValue();
}

QScriptValue script_help(QScriptContext *context, QScriptEngine *engine)
{
    QString result;
    for (int i = 0; i < context->argumentCount(); ++i) {
        if (i > 0)
            result.append(" ");
        result.append(context->argument(i).toString());
    }

    QScriptValue calleeData = context->callee().data();
    ScriptEnvironment *par = qobject_cast<ScriptEnvironment*>(calleeData.toQObject());
    par->print(result);
    return engine->undefinedValue();
}

QScriptValue script_window(QScriptContext *context, QScriptEngine *engine)
{
    QString result;
    for (int i = 0; i < context->argumentCount(); ++i) {
        if (i > 0)
            result.append(" ");

        result.append(context->argument(i).toString());
    }

    int i = context->argument(0).toInteger();

    QGraphicsView* vi = new QGraphicsView(new QGraphicsScene);
    vi->show();    

    NativeWindow* win = new NativeWindow((WId)i);
    win->setParent(vi);    
    vi->scene()->addWidget(win)->setScale(0.5);

    //win.move(0, 0);
    //win.resize(500, 300);

//    QScriptValue calleeData = context->callee().data();
//    ScriptEnvironment *par = qobject_cast<ScriptEnvironment*>(calleeData.toQObject());
//    par->print(result);
    return engine->undefinedValue();
}
